{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.7.3\n",
      "IPython 7.6.1\n",
      "\n",
      "torch 1.2.0\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Runs on CPU or GPU (if available)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deep Convolutional GAN"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn.functional as F\n",
    "from torchvision import datasets\n",
    "from torchvision import transforms\n",
    "import torch.nn as nn\n",
    "from torch.utils.data import DataLoader\n",
    "\n",
    "\n",
    "if torch.cuda.is_available():\n",
    "    torch.backends.cudnn.deterministic = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Settings and Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image batch dimensions: torch.Size([128, 1, 28, 28])\n",
      "Image label dimensions: torch.Size([128])\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### SETTINGS\n",
    "##########################\n",
    "\n",
    "# Device\n",
    "device = torch.device(\"cuda:1\" if torch.cuda.is_available() else \"cpu\")\n",
    "\n",
    "# Hyperparameters\n",
    "random_seed = 42\n",
    "generator_learning_rate = 0.0001\n",
    "discriminator_learning_rate = 0.0001\n",
    "NUM_EPOCHS = 100\n",
    "BATCH_SIZE = 128\n",
    "LATENT_DIM = 100\n",
    "IMG_SHAPE = (1, 28, 28)\n",
    "IMG_SIZE = 1\n",
    "for x in IMG_SHAPE:\n",
    "    IMG_SIZE *= x\n",
    "\n",
    "\n",
    "\n",
    "##########################\n",
    "### MNIST DATASET\n",
    "##########################\n",
    "\n",
    "# Note transforms.ToTensor() scales input images\n",
    "# to 0-1 range\n",
    "train_dataset = datasets.MNIST(root='data', \n",
    "                               train=True, \n",
    "                               transform=transforms.ToTensor(),\n",
    "                               download=True)\n",
    "\n",
    "test_dataset = datasets.MNIST(root='data', \n",
    "                              train=False, \n",
    "                              transform=transforms.ToTensor())\n",
    "\n",
    "\n",
    "train_loader = DataLoader(dataset=train_dataset, \n",
    "                          batch_size=BATCH_SIZE,\n",
    "                          num_workers=4,\n",
    "                          shuffle=True)\n",
    "\n",
    "test_loader = DataLoader(dataset=test_dataset, \n",
    "                         batch_size=BATCH_SIZE,\n",
    "                         num_workers=4,\n",
    "                         shuffle=False)\n",
    "\n",
    "# Checking the dataset\n",
    "for images, labels in train_loader:  \n",
    "    print('Image batch dimensions:', images.shape)\n",
    "    print('Image label dimensions:', labels.shape)\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "##########################\n",
    "### MODEL\n",
    "##########################\n",
    "\n",
    "class Flatten(nn.Module):\n",
    "    def forward(self, input):\n",
    "        return input.view(input.size(0), -1)\n",
    "    \n",
    "class Reshape1(nn.Module):\n",
    "    def forward(self, input):\n",
    "        return input.view(input.size(0), 64, 7, 7)\n",
    "\n",
    "\n",
    "class GAN(torch.nn.Module):\n",
    "\n",
    "    def __init__(self):\n",
    "        super(GAN, self).__init__()\n",
    "        \n",
    "        \n",
    "        self.generator = nn.Sequential(\n",
    "              \n",
    "            nn.Linear(LATENT_DIM, 3136, bias=False),\n",
    "            nn.BatchNorm1d(num_features=3136),\n",
    "            nn.LeakyReLU(inplace=True, negative_slope=0.0001),\n",
    "            Reshape1(),\n",
    "            \n",
    "            nn.ConvTranspose2d(in_channels=64, out_channels=32, kernel_size=(3, 3), stride=(2, 2), padding=1, bias=False),\n",
    "            nn.BatchNorm2d(num_features=32),\n",
    "            nn.LeakyReLU(inplace=True, negative_slope=0.0001),\n",
    "            #nn.Dropout2d(p=0.2),\n",
    "            \n",
    "            nn.ConvTranspose2d(in_channels=32, out_channels=16, kernel_size=(3, 3), stride=(2, 2), padding=1, bias=False),\n",
    "            nn.BatchNorm2d(num_features=16),\n",
    "            nn.LeakyReLU(inplace=True, negative_slope=0.0001),\n",
    "            #nn.Dropout2d(p=0.2),\n",
    "            \n",
    "            nn.ConvTranspose2d(in_channels=16, out_channels=8, kernel_size=(3, 3), stride=(1, 1), padding=0, bias=False),\n",
    "            nn.BatchNorm2d(num_features=8),\n",
    "            nn.LeakyReLU(inplace=True, negative_slope=0.0001),\n",
    "            #nn.Dropout2d(p=0.2),\n",
    "            \n",
    "            nn.ConvTranspose2d(in_channels=8, out_channels=1, kernel_size=(2, 2), stride=(1, 1), padding=0, bias=False),\n",
    "            nn.Tanh()\n",
    "        )\n",
    "        \n",
    "        self.discriminator = nn.Sequential(\n",
    "            nn.Conv2d(in_channels=1, out_channels=8, padding=1, kernel_size=(3, 3), stride=(2, 2), bias=False),\n",
    "            nn.BatchNorm2d(num_features=8),\n",
    "            nn.LeakyReLU(inplace=True, negative_slope=0.0001), \n",
    "            #nn.Dropout2d(p=0.2),\n",
    "            \n",
    "            nn.Conv2d(in_channels=8, out_channels=32, padding=1, kernel_size=(3, 3), stride=(2, 2), bias=False),\n",
    "            nn.BatchNorm2d(num_features=32),\n",
    "            nn.LeakyReLU(inplace=True, negative_slope=0.0001), \n",
    "            #nn.Dropout2d(p=0.2),\n",
    "            \n",
    "            Flatten(),\n",
    "\n",
    "            nn.Linear(7*7*32, 1),\n",
    "            #nn.Sigmoid()\n",
    "        )\n",
    "\n",
    "            \n",
    "    def generator_forward(self, z):\n",
    "        img = self.generator(z)\n",
    "        return img\n",
    "    \n",
    "    def discriminator_forward(self, img):\n",
    "        pred = model.discriminator(img)\n",
    "        return pred.view(-1)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GAN(\n",
      "  (generator): Sequential(\n",
      "    (0): Linear(in_features=100, out_features=3136, bias=False)\n",
      "    (1): BatchNorm1d(3136, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (2): LeakyReLU(negative_slope=0.0001, inplace=True)\n",
      "    (3): Reshape1()\n",
      "    (4): ConvTranspose2d(64, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (5): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (6): LeakyReLU(negative_slope=0.0001, inplace=True)\n",
      "    (7): ConvTranspose2d(32, 16, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (8): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (9): LeakyReLU(negative_slope=0.0001, inplace=True)\n",
      "    (10): ConvTranspose2d(16, 8, kernel_size=(3, 3), stride=(1, 1), bias=False)\n",
      "    (11): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (12): LeakyReLU(negative_slope=0.0001, inplace=True)\n",
      "    (13): ConvTranspose2d(8, 1, kernel_size=(2, 2), stride=(1, 1), bias=False)\n",
      "    (14): Tanh()\n",
      "  )\n",
      "  (discriminator): Sequential(\n",
      "    (0): Conv2d(1, 8, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (1): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (2): LeakyReLU(negative_slope=0.0001, inplace=True)\n",
      "    (3): Conv2d(8, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (4): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (5): LeakyReLU(negative_slope=0.0001, inplace=True)\n",
      "    (6): Flatten()\n",
      "    (7): Linear(in_features=1568, out_features=1, bias=True)\n",
      "  )\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "torch.manual_seed(random_seed)\n",
    "\n",
    "#del model\n",
    "model = GAN()\n",
    "model = model.to(device)\n",
    "\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\noutputs = []\\ndef hook(module, input, output):\\n    outputs.append(output)\\n\\n#for i, layer in enumerate(model.discriminator):\\n#    if isinstance(layer, torch.nn.modules.conv.Conv2d):\\n#        model.discriminator[i].register_forward_hook(hook)\\n\\nfor i, layer in enumerate(model.generator):\\n    if isinstance(layer, torch.nn.modules.ConvTranspose2d):\\n        model.generator[i].register_forward_hook(hook)\\n'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### ## FOR DEBUGGING\n",
    "\n",
    "\"\"\"\n",
    "outputs = []\n",
    "def hook(module, input, output):\n",
    "    outputs.append(output)\n",
    "\n",
    "#for i, layer in enumerate(model.discriminator):\n",
    "#    if isinstance(layer, torch.nn.modules.conv.Conv2d):\n",
    "#        model.discriminator[i].register_forward_hook(hook)\n",
    "\n",
    "for i, layer in enumerate(model.generator):\n",
    "    if isinstance(layer, torch.nn.modules.ConvTranspose2d):\n",
    "        model.generator[i].register_forward_hook(hook)\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "optim_gener = torch.optim.Adam(model.generator.parameters(), lr=generator_learning_rate)\n",
    "optim_discr = torch.optim.Adam(model.discriminator.parameters(), lr=discriminator_learning_rate)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 001/100 | Batch 000/469 | Gen/Dis Loss: 0.7042/0.6743\n",
      "Epoch: 001/100 | Batch 100/469 | Gen/Dis Loss: 1.3058/0.3250\n",
      "Epoch: 001/100 | Batch 200/469 | Gen/Dis Loss: 1.4384/0.2663\n",
      "Epoch: 001/100 | Batch 300/469 | Gen/Dis Loss: 1.6195/0.2611\n",
      "Epoch: 001/100 | Batch 400/469 | Gen/Dis Loss: 1.5340/0.3022\n",
      "Time elapsed: 0.19 min\n",
      "Epoch: 002/100 | Batch 000/469 | Gen/Dis Loss: 1.1456/0.4471\n",
      "Epoch: 002/100 | Batch 100/469 | Gen/Dis Loss: 1.1290/0.4476\n",
      "Epoch: 002/100 | Batch 200/469 | Gen/Dis Loss: 1.0849/0.4651\n",
      "Epoch: 002/100 | Batch 300/469 | Gen/Dis Loss: 1.0275/0.4765\n",
      "Epoch: 002/100 | Batch 400/469 | Gen/Dis Loss: 0.9861/0.4893\n",
      "Time elapsed: 0.37 min\n",
      "Epoch: 003/100 | Batch 000/469 | Gen/Dis Loss: 0.9710/0.5148\n",
      "Epoch: 003/100 | Batch 100/469 | Gen/Dis Loss: 0.9321/0.5574\n",
      "Epoch: 003/100 | Batch 200/469 | Gen/Dis Loss: 0.9129/0.5724\n",
      "Epoch: 003/100 | Batch 300/469 | Gen/Dis Loss: 0.9706/0.5348\n",
      "Epoch: 003/100 | Batch 400/469 | Gen/Dis Loss: 0.9026/0.5425\n",
      "Time elapsed: 0.57 min\n",
      "Epoch: 004/100 | Batch 000/469 | Gen/Dis Loss: 0.9785/0.5205\n",
      "Epoch: 004/100 | Batch 100/469 | Gen/Dis Loss: 0.9802/0.5120\n",
      "Epoch: 004/100 | Batch 200/469 | Gen/Dis Loss: 0.9916/0.5114\n",
      "Epoch: 004/100 | Batch 300/469 | Gen/Dis Loss: 0.9647/0.5268\n",
      "Epoch: 004/100 | Batch 400/469 | Gen/Dis Loss: 1.0392/0.5014\n",
      "Time elapsed: 0.76 min\n",
      "Epoch: 005/100 | Batch 000/469 | Gen/Dis Loss: 1.0477/0.5005\n",
      "Epoch: 005/100 | Batch 100/469 | Gen/Dis Loss: 0.9455/0.5028\n",
      "Epoch: 005/100 | Batch 200/469 | Gen/Dis Loss: 1.0274/0.5099\n",
      "Epoch: 005/100 | Batch 300/469 | Gen/Dis Loss: 0.9592/0.5301\n",
      "Epoch: 005/100 | Batch 400/469 | Gen/Dis Loss: 0.9769/0.5288\n",
      "Time elapsed: 0.94 min\n",
      "Epoch: 006/100 | Batch 000/469 | Gen/Dis Loss: 1.1041/0.4773\n",
      "Epoch: 006/100 | Batch 100/469 | Gen/Dis Loss: 1.0670/0.4941\n",
      "Epoch: 006/100 | Batch 200/469 | Gen/Dis Loss: 1.0629/0.4827\n",
      "Epoch: 006/100 | Batch 300/469 | Gen/Dis Loss: 1.0223/0.4908\n",
      "Epoch: 006/100 | Batch 400/469 | Gen/Dis Loss: 1.1509/0.4545\n",
      "Time elapsed: 1.14 min\n",
      "Epoch: 007/100 | Batch 000/469 | Gen/Dis Loss: 1.1102/0.4551\n",
      "Epoch: 007/100 | Batch 100/469 | Gen/Dis Loss: 1.0865/0.4770\n",
      "Epoch: 007/100 | Batch 200/469 | Gen/Dis Loss: 1.1400/0.4882\n",
      "Epoch: 007/100 | Batch 300/469 | Gen/Dis Loss: 1.1405/0.4388\n",
      "Epoch: 007/100 | Batch 400/469 | Gen/Dis Loss: 1.0639/0.5024\n",
      "Time elapsed: 1.33 min\n",
      "Epoch: 008/100 | Batch 000/469 | Gen/Dis Loss: 1.1032/0.4786\n",
      "Epoch: 008/100 | Batch 100/469 | Gen/Dis Loss: 1.1949/0.4811\n",
      "Epoch: 008/100 | Batch 200/469 | Gen/Dis Loss: 1.0076/0.4845\n",
      "Epoch: 008/100 | Batch 300/469 | Gen/Dis Loss: 1.1185/0.4682\n",
      "Epoch: 008/100 | Batch 400/469 | Gen/Dis Loss: 1.0211/0.4773\n",
      "Time elapsed: 1.51 min\n",
      "Epoch: 009/100 | Batch 000/469 | Gen/Dis Loss: 1.1309/0.4880\n",
      "Epoch: 009/100 | Batch 100/469 | Gen/Dis Loss: 1.1688/0.4936\n",
      "Epoch: 009/100 | Batch 200/469 | Gen/Dis Loss: 1.0846/0.4920\n",
      "Epoch: 009/100 | Batch 300/469 | Gen/Dis Loss: 1.0401/0.4875\n",
      "Epoch: 009/100 | Batch 400/469 | Gen/Dis Loss: 1.1135/0.4437\n",
      "Time elapsed: 1.69 min\n",
      "Epoch: 010/100 | Batch 000/469 | Gen/Dis Loss: 1.1250/0.4552\n",
      "Epoch: 010/100 | Batch 100/469 | Gen/Dis Loss: 1.1869/0.4754\n",
      "Epoch: 010/100 | Batch 200/469 | Gen/Dis Loss: 1.0266/0.5211\n",
      "Epoch: 010/100 | Batch 300/469 | Gen/Dis Loss: 1.0281/0.4855\n",
      "Epoch: 010/100 | Batch 400/469 | Gen/Dis Loss: 1.1443/0.5059\n",
      "Time elapsed: 1.86 min\n",
      "Epoch: 011/100 | Batch 000/469 | Gen/Dis Loss: 1.1782/0.4433\n",
      "Epoch: 011/100 | Batch 100/469 | Gen/Dis Loss: 1.2944/0.4828\n",
      "Epoch: 011/100 | Batch 200/469 | Gen/Dis Loss: 1.2939/0.4710\n",
      "Epoch: 011/100 | Batch 300/469 | Gen/Dis Loss: 0.9880/0.5353\n",
      "Epoch: 011/100 | Batch 400/469 | Gen/Dis Loss: 1.0860/0.5044\n",
      "Time elapsed: 2.04 min\n",
      "Epoch: 012/100 | Batch 000/469 | Gen/Dis Loss: 1.0354/0.4889\n",
      "Epoch: 012/100 | Batch 100/469 | Gen/Dis Loss: 1.0483/0.4908\n",
      "Epoch: 012/100 | Batch 200/469 | Gen/Dis Loss: 1.0234/0.5043\n",
      "Epoch: 012/100 | Batch 300/469 | Gen/Dis Loss: 1.2044/0.4811\n",
      "Epoch: 012/100 | Batch 400/469 | Gen/Dis Loss: 1.1738/0.4902\n",
      "Time elapsed: 2.21 min\n",
      "Epoch: 013/100 | Batch 000/469 | Gen/Dis Loss: 1.1903/0.4955\n",
      "Epoch: 013/100 | Batch 100/469 | Gen/Dis Loss: 1.1368/0.5403\n",
      "Epoch: 013/100 | Batch 200/469 | Gen/Dis Loss: 1.0993/0.4859\n",
      "Epoch: 013/100 | Batch 300/469 | Gen/Dis Loss: 1.0989/0.5293\n",
      "Epoch: 013/100 | Batch 400/469 | Gen/Dis Loss: 1.0223/0.5568\n",
      "Time elapsed: 2.40 min\n",
      "Epoch: 014/100 | Batch 000/469 | Gen/Dis Loss: 1.1139/0.5405\n",
      "Epoch: 014/100 | Batch 100/469 | Gen/Dis Loss: 1.1770/0.4788\n",
      "Epoch: 014/100 | Batch 200/469 | Gen/Dis Loss: 1.1685/0.4993\n",
      "Epoch: 014/100 | Batch 300/469 | Gen/Dis Loss: 1.0546/0.5169\n",
      "Epoch: 014/100 | Batch 400/469 | Gen/Dis Loss: 1.1147/0.5244\n",
      "Time elapsed: 2.59 min\n",
      "Epoch: 015/100 | Batch 000/469 | Gen/Dis Loss: 0.9739/0.5662\n",
      "Epoch: 015/100 | Batch 100/469 | Gen/Dis Loss: 0.9286/0.5574\n",
      "Epoch: 015/100 | Batch 200/469 | Gen/Dis Loss: 1.0893/0.5187\n",
      "Epoch: 015/100 | Batch 300/469 | Gen/Dis Loss: 1.0183/0.5348\n",
      "Epoch: 015/100 | Batch 400/469 | Gen/Dis Loss: 1.0253/0.5727\n",
      "Time elapsed: 2.78 min\n",
      "Epoch: 016/100 | Batch 000/469 | Gen/Dis Loss: 1.0393/0.5658\n",
      "Epoch: 016/100 | Batch 100/469 | Gen/Dis Loss: 0.9653/0.5572\n",
      "Epoch: 016/100 | Batch 200/469 | Gen/Dis Loss: 1.1106/0.5044\n",
      "Epoch: 016/100 | Batch 300/469 | Gen/Dis Loss: 1.0155/0.5480\n",
      "Epoch: 016/100 | Batch 400/469 | Gen/Dis Loss: 1.0312/0.5223\n",
      "Time elapsed: 2.96 min\n",
      "Epoch: 017/100 | Batch 000/469 | Gen/Dis Loss: 1.0040/0.5840\n",
      "Epoch: 017/100 | Batch 100/469 | Gen/Dis Loss: 1.0765/0.5318\n",
      "Epoch: 017/100 | Batch 200/469 | Gen/Dis Loss: 1.0712/0.5204\n",
      "Epoch: 017/100 | Batch 300/469 | Gen/Dis Loss: 1.0746/0.5833\n",
      "Epoch: 017/100 | Batch 400/469 | Gen/Dis Loss: 1.0548/0.5324\n",
      "Time elapsed: 3.15 min\n",
      "Epoch: 018/100 | Batch 000/469 | Gen/Dis Loss: 0.9197/0.5617\n",
      "Epoch: 018/100 | Batch 100/469 | Gen/Dis Loss: 1.0251/0.5290\n",
      "Epoch: 018/100 | Batch 200/469 | Gen/Dis Loss: 0.9719/0.5501\n",
      "Epoch: 018/100 | Batch 300/469 | Gen/Dis Loss: 1.0612/0.5575\n",
      "Epoch: 018/100 | Batch 400/469 | Gen/Dis Loss: 0.9316/0.5657\n",
      "Time elapsed: 3.34 min\n",
      "Epoch: 019/100 | Batch 000/469 | Gen/Dis Loss: 0.9538/0.5692\n",
      "Epoch: 019/100 | Batch 100/469 | Gen/Dis Loss: 0.9766/0.5171\n",
      "Epoch: 019/100 | Batch 200/469 | Gen/Dis Loss: 1.1488/0.4569\n",
      "Epoch: 019/100 | Batch 300/469 | Gen/Dis Loss: 0.9186/0.5640\n",
      "Epoch: 019/100 | Batch 400/469 | Gen/Dis Loss: 0.9183/0.6167\n",
      "Time elapsed: 3.52 min\n",
      "Epoch: 020/100 | Batch 000/469 | Gen/Dis Loss: 1.0272/0.5424\n",
      "Epoch: 020/100 | Batch 100/469 | Gen/Dis Loss: 0.9360/0.6114\n",
      "Epoch: 020/100 | Batch 200/469 | Gen/Dis Loss: 1.0169/0.5299\n",
      "Epoch: 020/100 | Batch 300/469 | Gen/Dis Loss: 1.0314/0.5425\n",
      "Epoch: 020/100 | Batch 400/469 | Gen/Dis Loss: 0.9730/0.5540\n",
      "Time elapsed: 3.70 min\n",
      "Epoch: 021/100 | Batch 000/469 | Gen/Dis Loss: 1.0281/0.5627\n",
      "Epoch: 021/100 | Batch 100/469 | Gen/Dis Loss: 1.0060/0.6017\n",
      "Epoch: 021/100 | Batch 200/469 | Gen/Dis Loss: 1.0429/0.5913\n",
      "Epoch: 021/100 | Batch 300/469 | Gen/Dis Loss: 1.0129/0.5390\n",
      "Epoch: 021/100 | Batch 400/469 | Gen/Dis Loss: 1.0230/0.5921\n",
      "Time elapsed: 3.88 min\n",
      "Epoch: 022/100 | Batch 000/469 | Gen/Dis Loss: 0.8210/0.5850\n",
      "Epoch: 022/100 | Batch 100/469 | Gen/Dis Loss: 0.9765/0.6000\n",
      "Epoch: 022/100 | Batch 200/469 | Gen/Dis Loss: 0.9104/0.5788\n",
      "Epoch: 022/100 | Batch 300/469 | Gen/Dis Loss: 0.8663/0.5950\n",
      "Epoch: 022/100 | Batch 400/469 | Gen/Dis Loss: 1.0385/0.5803\n",
      "Time elapsed: 4.07 min\n",
      "Epoch: 023/100 | Batch 000/469 | Gen/Dis Loss: 0.9640/0.5412\n",
      "Epoch: 023/100 | Batch 100/469 | Gen/Dis Loss: 0.9348/0.5825\n",
      "Epoch: 023/100 | Batch 200/469 | Gen/Dis Loss: 1.0439/0.5931\n",
      "Epoch: 023/100 | Batch 300/469 | Gen/Dis Loss: 1.0064/0.6169\n",
      "Epoch: 023/100 | Batch 400/469 | Gen/Dis Loss: 0.9615/0.5814\n",
      "Time elapsed: 4.26 min\n",
      "Epoch: 024/100 | Batch 000/469 | Gen/Dis Loss: 0.9748/0.5527\n",
      "Epoch: 024/100 | Batch 100/469 | Gen/Dis Loss: 0.9593/0.5664\n",
      "Epoch: 024/100 | Batch 200/469 | Gen/Dis Loss: 0.8329/0.6269\n",
      "Epoch: 024/100 | Batch 300/469 | Gen/Dis Loss: 0.9947/0.6028\n",
      "Epoch: 024/100 | Batch 400/469 | Gen/Dis Loss: 0.9175/0.6207\n",
      "Time elapsed: 4.44 min\n",
      "Epoch: 025/100 | Batch 000/469 | Gen/Dis Loss: 0.9711/0.6147\n",
      "Epoch: 025/100 | Batch 100/469 | Gen/Dis Loss: 0.8441/0.5788\n",
      "Epoch: 025/100 | Batch 200/469 | Gen/Dis Loss: 0.8804/0.6257\n",
      "Epoch: 025/100 | Batch 300/469 | Gen/Dis Loss: 0.8894/0.6305\n",
      "Epoch: 025/100 | Batch 400/469 | Gen/Dis Loss: 1.0003/0.5611\n",
      "Time elapsed: 4.62 min\n",
      "Epoch: 026/100 | Batch 000/469 | Gen/Dis Loss: 0.9185/0.5670\n",
      "Epoch: 026/100 | Batch 100/469 | Gen/Dis Loss: 0.8038/0.6254\n",
      "Epoch: 026/100 | Batch 200/469 | Gen/Dis Loss: 0.9098/0.6414\n",
      "Epoch: 026/100 | Batch 300/469 | Gen/Dis Loss: 0.9220/0.6424\n",
      "Epoch: 026/100 | Batch 400/469 | Gen/Dis Loss: 0.9396/0.6200\n",
      "Time elapsed: 4.80 min\n",
      "Epoch: 027/100 | Batch 000/469 | Gen/Dis Loss: 0.9383/0.5994\n",
      "Epoch: 027/100 | Batch 100/469 | Gen/Dis Loss: 0.9374/0.6290\n",
      "Epoch: 027/100 | Batch 200/469 | Gen/Dis Loss: 0.9360/0.5682\n",
      "Epoch: 027/100 | Batch 300/469 | Gen/Dis Loss: 0.9031/0.6194\n",
      "Epoch: 027/100 | Batch 400/469 | Gen/Dis Loss: 0.9073/0.6276\n",
      "Time elapsed: 4.97 min\n",
      "Epoch: 028/100 | Batch 000/469 | Gen/Dis Loss: 0.9361/0.6210\n",
      "Epoch: 028/100 | Batch 100/469 | Gen/Dis Loss: 0.9590/0.6085\n",
      "Epoch: 028/100 | Batch 200/469 | Gen/Dis Loss: 0.9330/0.6403\n",
      "Epoch: 028/100 | Batch 300/469 | Gen/Dis Loss: 0.8401/0.6287\n",
      "Epoch: 028/100 | Batch 400/469 | Gen/Dis Loss: 0.9091/0.5869\n",
      "Time elapsed: 5.15 min\n",
      "Epoch: 029/100 | Batch 000/469 | Gen/Dis Loss: 1.0263/0.5919\n",
      "Epoch: 029/100 | Batch 100/469 | Gen/Dis Loss: 0.9032/0.6344\n",
      "Epoch: 029/100 | Batch 200/469 | Gen/Dis Loss: 0.9062/0.6374\n",
      "Epoch: 029/100 | Batch 300/469 | Gen/Dis Loss: 0.8570/0.6521\n",
      "Epoch: 029/100 | Batch 400/469 | Gen/Dis Loss: 0.8176/0.6735\n",
      "Time elapsed: 5.33 min\n",
      "Epoch: 030/100 | Batch 000/469 | Gen/Dis Loss: 0.8319/0.6868\n",
      "Epoch: 030/100 | Batch 100/469 | Gen/Dis Loss: 0.8666/0.6535\n",
      "Epoch: 030/100 | Batch 200/469 | Gen/Dis Loss: 0.8510/0.6624\n",
      "Epoch: 030/100 | Batch 300/469 | Gen/Dis Loss: 0.8705/0.6354\n",
      "Epoch: 030/100 | Batch 400/469 | Gen/Dis Loss: 0.8534/0.6467\n",
      "Time elapsed: 5.52 min\n",
      "Epoch: 031/100 | Batch 000/469 | Gen/Dis Loss: 0.9562/0.6488\n",
      "Epoch: 031/100 | Batch 100/469 | Gen/Dis Loss: 0.8501/0.6209\n",
      "Epoch: 031/100 | Batch 200/469 | Gen/Dis Loss: 0.8582/0.6281\n",
      "Epoch: 031/100 | Batch 300/469 | Gen/Dis Loss: 0.8317/0.6526\n",
      "Epoch: 031/100 | Batch 400/469 | Gen/Dis Loss: 0.8294/0.6443\n",
      "Time elapsed: 5.70 min\n",
      "Epoch: 032/100 | Batch 000/469 | Gen/Dis Loss: 0.8732/0.6642\n",
      "Epoch: 032/100 | Batch 100/469 | Gen/Dis Loss: 0.9039/0.5738\n",
      "Epoch: 032/100 | Batch 200/469 | Gen/Dis Loss: 0.9144/0.6086\n",
      "Epoch: 032/100 | Batch 300/469 | Gen/Dis Loss: 0.9018/0.6199\n",
      "Epoch: 032/100 | Batch 400/469 | Gen/Dis Loss: 0.9000/0.6288\n",
      "Time elapsed: 5.89 min\n",
      "Epoch: 033/100 | Batch 000/469 | Gen/Dis Loss: 0.9015/0.6006\n",
      "Epoch: 033/100 | Batch 100/469 | Gen/Dis Loss: 0.8965/0.6364\n",
      "Epoch: 033/100 | Batch 200/469 | Gen/Dis Loss: 0.8716/0.6174\n",
      "Epoch: 033/100 | Batch 300/469 | Gen/Dis Loss: 0.7849/0.6481\n",
      "Epoch: 033/100 | Batch 400/469 | Gen/Dis Loss: 0.8660/0.6665\n",
      "Time elapsed: 6.08 min\n",
      "Epoch: 034/100 | Batch 000/469 | Gen/Dis Loss: 0.8753/0.6632\n",
      "Epoch: 034/100 | Batch 100/469 | Gen/Dis Loss: 0.8555/0.6768\n",
      "Epoch: 034/100 | Batch 200/469 | Gen/Dis Loss: 0.9026/0.6141\n",
      "Epoch: 034/100 | Batch 300/469 | Gen/Dis Loss: 0.8592/0.6660\n",
      "Epoch: 034/100 | Batch 400/469 | Gen/Dis Loss: 0.8328/0.6547\n",
      "Time elapsed: 6.26 min\n",
      "Epoch: 035/100 | Batch 000/469 | Gen/Dis Loss: 0.8191/0.6640\n",
      "Epoch: 035/100 | Batch 100/469 | Gen/Dis Loss: 0.8682/0.6384\n",
      "Epoch: 035/100 | Batch 200/469 | Gen/Dis Loss: 0.8659/0.6529\n",
      "Epoch: 035/100 | Batch 300/469 | Gen/Dis Loss: 0.7945/0.6897\n",
      "Epoch: 035/100 | Batch 400/469 | Gen/Dis Loss: 0.8761/0.6396\n",
      "Time elapsed: 6.44 min\n",
      "Epoch: 036/100 | Batch 000/469 | Gen/Dis Loss: 0.7889/0.6610\n",
      "Epoch: 036/100 | Batch 100/469 | Gen/Dis Loss: 0.8540/0.6306\n",
      "Epoch: 036/100 | Batch 200/469 | Gen/Dis Loss: 0.8731/0.6181\n",
      "Epoch: 036/100 | Batch 300/469 | Gen/Dis Loss: 0.8459/0.6869\n",
      "Epoch: 036/100 | Batch 400/469 | Gen/Dis Loss: 0.9194/0.7013\n",
      "Time elapsed: 6.66 min\n",
      "Epoch: 037/100 | Batch 000/469 | Gen/Dis Loss: 0.8651/0.6302\n",
      "Epoch: 037/100 | Batch 100/469 | Gen/Dis Loss: 0.8718/0.6649\n",
      "Epoch: 037/100 | Batch 200/469 | Gen/Dis Loss: 0.8470/0.6905\n",
      "Epoch: 037/100 | Batch 300/469 | Gen/Dis Loss: 0.8514/0.6743\n",
      "Epoch: 037/100 | Batch 400/469 | Gen/Dis Loss: 0.8256/0.6896\n",
      "Time elapsed: 6.84 min\n",
      "Epoch: 038/100 | Batch 000/469 | Gen/Dis Loss: 0.7981/0.6623\n",
      "Epoch: 038/100 | Batch 100/469 | Gen/Dis Loss: 0.8720/0.6330\n",
      "Epoch: 038/100 | Batch 200/469 | Gen/Dis Loss: 0.8146/0.6613\n",
      "Epoch: 038/100 | Batch 300/469 | Gen/Dis Loss: 0.7763/0.6666\n",
      "Epoch: 038/100 | Batch 400/469 | Gen/Dis Loss: 0.8228/0.6759\n",
      "Time elapsed: 7.03 min\n",
      "Epoch: 039/100 | Batch 000/469 | Gen/Dis Loss: 0.7860/0.6432\n",
      "Epoch: 039/100 | Batch 100/469 | Gen/Dis Loss: 0.7736/0.6537\n",
      "Epoch: 039/100 | Batch 200/469 | Gen/Dis Loss: 0.8010/0.6488\n",
      "Epoch: 039/100 | Batch 300/469 | Gen/Dis Loss: 0.7907/0.6811\n",
      "Epoch: 039/100 | Batch 400/469 | Gen/Dis Loss: 0.8156/0.6962\n",
      "Time elapsed: 7.22 min\n",
      "Epoch: 040/100 | Batch 000/469 | Gen/Dis Loss: 0.8877/0.6374\n",
      "Epoch: 040/100 | Batch 100/469 | Gen/Dis Loss: 0.8237/0.6674\n",
      "Epoch: 040/100 | Batch 200/469 | Gen/Dis Loss: 0.7927/0.6621\n",
      "Epoch: 040/100 | Batch 300/469 | Gen/Dis Loss: 0.8991/0.6347\n",
      "Epoch: 040/100 | Batch 400/469 | Gen/Dis Loss: 0.7980/0.6735\n",
      "Time elapsed: 7.41 min\n",
      "Epoch: 041/100 | Batch 000/469 | Gen/Dis Loss: 0.8294/0.6596\n",
      "Epoch: 041/100 | Batch 100/469 | Gen/Dis Loss: 0.8119/0.6490\n",
      "Epoch: 041/100 | Batch 200/469 | Gen/Dis Loss: 0.8270/0.6643\n",
      "Epoch: 041/100 | Batch 300/469 | Gen/Dis Loss: 0.8329/0.6330\n",
      "Epoch: 041/100 | Batch 400/469 | Gen/Dis Loss: 0.8065/0.6905\n",
      "Time elapsed: 7.60 min\n",
      "Epoch: 042/100 | Batch 000/469 | Gen/Dis Loss: 0.8127/0.6444\n",
      "Epoch: 042/100 | Batch 100/469 | Gen/Dis Loss: 0.8496/0.6829\n",
      "Epoch: 042/100 | Batch 200/469 | Gen/Dis Loss: 0.7432/0.6781\n",
      "Epoch: 042/100 | Batch 300/469 | Gen/Dis Loss: 0.8063/0.6520\n",
      "Epoch: 042/100 | Batch 400/469 | Gen/Dis Loss: 0.7978/0.6950\n",
      "Time elapsed: 7.79 min\n",
      "Epoch: 043/100 | Batch 000/469 | Gen/Dis Loss: 0.7393/0.6981\n",
      "Epoch: 043/100 | Batch 100/469 | Gen/Dis Loss: 0.7949/0.6436\n",
      "Epoch: 043/100 | Batch 200/469 | Gen/Dis Loss: 0.7263/0.6792\n",
      "Epoch: 043/100 | Batch 300/469 | Gen/Dis Loss: 0.8445/0.6574\n",
      "Epoch: 043/100 | Batch 400/469 | Gen/Dis Loss: 0.8083/0.6932\n",
      "Time elapsed: 7.98 min\n",
      "Epoch: 044/100 | Batch 000/469 | Gen/Dis Loss: 0.8016/0.6728\n",
      "Epoch: 044/100 | Batch 100/469 | Gen/Dis Loss: 0.8368/0.6798\n",
      "Epoch: 044/100 | Batch 200/469 | Gen/Dis Loss: 0.7767/0.6624\n",
      "Epoch: 044/100 | Batch 300/469 | Gen/Dis Loss: 0.8159/0.7030\n",
      "Epoch: 044/100 | Batch 400/469 | Gen/Dis Loss: 0.7738/0.6814\n",
      "Time elapsed: 8.17 min\n",
      "Epoch: 045/100 | Batch 000/469 | Gen/Dis Loss: 0.7911/0.6656\n",
      "Epoch: 045/100 | Batch 100/469 | Gen/Dis Loss: 0.7467/0.6722\n",
      "Epoch: 045/100 | Batch 200/469 | Gen/Dis Loss: 0.8361/0.6641\n",
      "Epoch: 045/100 | Batch 300/469 | Gen/Dis Loss: 0.8219/0.6827\n",
      "Epoch: 045/100 | Batch 400/469 | Gen/Dis Loss: 0.7924/0.6497\n",
      "Time elapsed: 8.36 min\n",
      "Epoch: 046/100 | Batch 000/469 | Gen/Dis Loss: 0.7680/0.6488\n",
      "Epoch: 046/100 | Batch 100/469 | Gen/Dis Loss: 0.7731/0.6371\n",
      "Epoch: 046/100 | Batch 200/469 | Gen/Dis Loss: 0.7511/0.6632\n",
      "Epoch: 046/100 | Batch 300/469 | Gen/Dis Loss: 0.7988/0.6634\n",
      "Epoch: 046/100 | Batch 400/469 | Gen/Dis Loss: 0.7706/0.6666\n",
      "Time elapsed: 8.54 min\n",
      "Epoch: 047/100 | Batch 000/469 | Gen/Dis Loss: 0.8048/0.6702\n",
      "Epoch: 047/100 | Batch 100/469 | Gen/Dis Loss: 0.8293/0.6751\n",
      "Epoch: 047/100 | Batch 200/469 | Gen/Dis Loss: 0.8024/0.6686\n",
      "Epoch: 047/100 | Batch 300/469 | Gen/Dis Loss: 0.7915/0.6438\n",
      "Epoch: 047/100 | Batch 400/469 | Gen/Dis Loss: 0.7823/0.6841\n",
      "Time elapsed: 8.72 min\n",
      "Epoch: 048/100 | Batch 000/469 | Gen/Dis Loss: 0.8267/0.6457\n",
      "Epoch: 048/100 | Batch 100/469 | Gen/Dis Loss: 0.7614/0.6931\n",
      "Epoch: 048/100 | Batch 200/469 | Gen/Dis Loss: 0.7751/0.6927\n",
      "Epoch: 048/100 | Batch 300/469 | Gen/Dis Loss: 0.7868/0.6658\n",
      "Epoch: 048/100 | Batch 400/469 | Gen/Dis Loss: 0.7797/0.6885\n",
      "Time elapsed: 8.90 min\n",
      "Epoch: 049/100 | Batch 000/469 | Gen/Dis Loss: 0.7799/0.6506\n",
      "Epoch: 049/100 | Batch 100/469 | Gen/Dis Loss: 0.8884/0.6786\n",
      "Epoch: 049/100 | Batch 200/469 | Gen/Dis Loss: 0.7651/0.6634\n",
      "Epoch: 049/100 | Batch 300/469 | Gen/Dis Loss: 0.7538/0.6758\n",
      "Epoch: 049/100 | Batch 400/469 | Gen/Dis Loss: 0.7760/0.6950\n",
      "Time elapsed: 9.08 min\n",
      "Epoch: 050/100 | Batch 000/469 | Gen/Dis Loss: 0.7811/0.6833\n",
      "Epoch: 050/100 | Batch 100/469 | Gen/Dis Loss: 0.7777/0.6739\n",
      "Epoch: 050/100 | Batch 200/469 | Gen/Dis Loss: 0.7786/0.6908\n",
      "Epoch: 050/100 | Batch 300/469 | Gen/Dis Loss: 0.7416/0.7097\n",
      "Epoch: 050/100 | Batch 400/469 | Gen/Dis Loss: 0.7953/0.6441\n",
      "Time elapsed: 9.26 min\n",
      "Epoch: 051/100 | Batch 000/469 | Gen/Dis Loss: 0.8031/0.6554\n",
      "Epoch: 051/100 | Batch 100/469 | Gen/Dis Loss: 0.7401/0.6747\n",
      "Epoch: 051/100 | Batch 200/469 | Gen/Dis Loss: 0.8171/0.7023\n",
      "Epoch: 051/100 | Batch 300/469 | Gen/Dis Loss: 0.7133/0.7171\n",
      "Epoch: 051/100 | Batch 400/469 | Gen/Dis Loss: 0.7473/0.6879\n",
      "Time elapsed: 9.45 min\n",
      "Epoch: 052/100 | Batch 000/469 | Gen/Dis Loss: 0.7421/0.6984\n",
      "Epoch: 052/100 | Batch 100/469 | Gen/Dis Loss: 0.7648/0.6513\n",
      "Epoch: 052/100 | Batch 200/469 | Gen/Dis Loss: 0.7021/0.6979\n",
      "Epoch: 052/100 | Batch 300/469 | Gen/Dis Loss: 0.7776/0.6661\n",
      "Epoch: 052/100 | Batch 400/469 | Gen/Dis Loss: 0.8062/0.6475\n",
      "Time elapsed: 9.64 min\n",
      "Epoch: 053/100 | Batch 000/469 | Gen/Dis Loss: 0.8263/0.7115\n",
      "Epoch: 053/100 | Batch 100/469 | Gen/Dis Loss: 0.7361/0.6831\n",
      "Epoch: 053/100 | Batch 200/469 | Gen/Dis Loss: 0.7696/0.6979\n",
      "Epoch: 053/100 | Batch 300/469 | Gen/Dis Loss: 0.8046/0.6792\n",
      "Epoch: 053/100 | Batch 400/469 | Gen/Dis Loss: 0.7493/0.6789\n",
      "Time elapsed: 9.83 min\n",
      "Epoch: 054/100 | Batch 000/469 | Gen/Dis Loss: 0.7835/0.6666\n",
      "Epoch: 054/100 | Batch 100/469 | Gen/Dis Loss: 0.7686/0.7022\n",
      "Epoch: 054/100 | Batch 200/469 | Gen/Dis Loss: 0.8027/0.6755\n",
      "Epoch: 054/100 | Batch 300/469 | Gen/Dis Loss: 0.7231/0.6783\n",
      "Epoch: 054/100 | Batch 400/469 | Gen/Dis Loss: 0.7606/0.6695\n",
      "Time elapsed: 10.02 min\n",
      "Epoch: 055/100 | Batch 000/469 | Gen/Dis Loss: 0.7433/0.6899\n",
      "Epoch: 055/100 | Batch 100/469 | Gen/Dis Loss: 0.7530/0.7002\n",
      "Epoch: 055/100 | Batch 200/469 | Gen/Dis Loss: 0.7508/0.6859\n",
      "Epoch: 055/100 | Batch 300/469 | Gen/Dis Loss: 0.7509/0.6886\n",
      "Epoch: 055/100 | Batch 400/469 | Gen/Dis Loss: 0.8238/0.6777\n",
      "Time elapsed: 10.19 min\n",
      "Epoch: 056/100 | Batch 000/469 | Gen/Dis Loss: 0.7396/0.6836\n",
      "Epoch: 056/100 | Batch 100/469 | Gen/Dis Loss: 0.8296/0.6512\n",
      "Epoch: 056/100 | Batch 200/469 | Gen/Dis Loss: 0.7735/0.6803\n",
      "Epoch: 056/100 | Batch 300/469 | Gen/Dis Loss: 0.7542/0.6854\n",
      "Epoch: 056/100 | Batch 400/469 | Gen/Dis Loss: 0.7773/0.6647\n",
      "Time elapsed: 10.36 min\n",
      "Epoch: 057/100 | Batch 000/469 | Gen/Dis Loss: 0.6869/0.7104\n",
      "Epoch: 057/100 | Batch 100/469 | Gen/Dis Loss: 0.7571/0.6782\n",
      "Epoch: 057/100 | Batch 200/469 | Gen/Dis Loss: 0.7453/0.6853\n",
      "Epoch: 057/100 | Batch 300/469 | Gen/Dis Loss: 0.7503/0.6680\n",
      "Epoch: 057/100 | Batch 400/469 | Gen/Dis Loss: 0.7822/0.6613\n",
      "Time elapsed: 10.55 min\n",
      "Epoch: 058/100 | Batch 000/469 | Gen/Dis Loss: 0.7451/0.6950\n",
      "Epoch: 058/100 | Batch 100/469 | Gen/Dis Loss: 0.7558/0.6745\n",
      "Epoch: 058/100 | Batch 200/469 | Gen/Dis Loss: 0.7261/0.6868\n",
      "Epoch: 058/100 | Batch 300/469 | Gen/Dis Loss: 0.7466/0.6538\n",
      "Epoch: 058/100 | Batch 400/469 | Gen/Dis Loss: 0.7235/0.6995\n",
      "Time elapsed: 10.75 min\n",
      "Epoch: 059/100 | Batch 000/469 | Gen/Dis Loss: 0.7853/0.6637\n",
      "Epoch: 059/100 | Batch 100/469 | Gen/Dis Loss: 0.7692/0.6566\n",
      "Epoch: 059/100 | Batch 200/469 | Gen/Dis Loss: 0.7777/0.6619\n",
      "Epoch: 059/100 | Batch 300/469 | Gen/Dis Loss: 0.7503/0.6659\n",
      "Epoch: 059/100 | Batch 400/469 | Gen/Dis Loss: 0.7200/0.7232\n",
      "Time elapsed: 10.94 min\n",
      "Epoch: 060/100 | Batch 000/469 | Gen/Dis Loss: 0.7252/0.6908\n",
      "Epoch: 060/100 | Batch 100/469 | Gen/Dis Loss: 0.7552/0.6910\n",
      "Epoch: 060/100 | Batch 200/469 | Gen/Dis Loss: 0.7648/0.6857\n",
      "Epoch: 060/100 | Batch 300/469 | Gen/Dis Loss: 0.7886/0.6721\n",
      "Epoch: 060/100 | Batch 400/469 | Gen/Dis Loss: 0.7599/0.7122\n",
      "Time elapsed: 11.12 min\n",
      "Epoch: 061/100 | Batch 000/469 | Gen/Dis Loss: 0.7162/0.6678\n",
      "Epoch: 061/100 | Batch 100/469 | Gen/Dis Loss: 0.7464/0.7128\n",
      "Epoch: 061/100 | Batch 200/469 | Gen/Dis Loss: 0.7318/0.6874\n",
      "Epoch: 061/100 | Batch 300/469 | Gen/Dis Loss: 0.7951/0.6544\n",
      "Epoch: 061/100 | Batch 400/469 | Gen/Dis Loss: 0.7648/0.6593\n",
      "Time elapsed: 11.31 min\n",
      "Epoch: 062/100 | Batch 000/469 | Gen/Dis Loss: 0.7877/0.6887\n",
      "Epoch: 062/100 | Batch 100/469 | Gen/Dis Loss: 0.7634/0.6638\n",
      "Epoch: 062/100 | Batch 200/469 | Gen/Dis Loss: 0.7410/0.6934\n",
      "Epoch: 062/100 | Batch 300/469 | Gen/Dis Loss: 0.7609/0.6808\n",
      "Epoch: 062/100 | Batch 400/469 | Gen/Dis Loss: 0.7256/0.7026\n",
      "Time elapsed: 11.50 min\n",
      "Epoch: 063/100 | Batch 000/469 | Gen/Dis Loss: 0.7176/0.6757\n",
      "Epoch: 063/100 | Batch 100/469 | Gen/Dis Loss: 0.7205/0.6757\n",
      "Epoch: 063/100 | Batch 200/469 | Gen/Dis Loss: 0.7680/0.7091\n",
      "Epoch: 063/100 | Batch 300/469 | Gen/Dis Loss: 0.7366/0.6609\n",
      "Epoch: 063/100 | Batch 400/469 | Gen/Dis Loss: 0.7274/0.6871\n",
      "Time elapsed: 11.69 min\n",
      "Epoch: 064/100 | Batch 000/469 | Gen/Dis Loss: 0.7007/0.7226\n",
      "Epoch: 064/100 | Batch 100/469 | Gen/Dis Loss: 0.7355/0.6728\n",
      "Epoch: 064/100 | Batch 200/469 | Gen/Dis Loss: 0.7557/0.6936\n",
      "Epoch: 064/100 | Batch 300/469 | Gen/Dis Loss: 0.7437/0.6898\n",
      "Epoch: 064/100 | Batch 400/469 | Gen/Dis Loss: 0.7512/0.7044\n",
      "Time elapsed: 11.87 min\n",
      "Epoch: 065/100 | Batch 000/469 | Gen/Dis Loss: 0.7302/0.6740\n",
      "Epoch: 065/100 | Batch 100/469 | Gen/Dis Loss: 0.7775/0.6942\n",
      "Epoch: 065/100 | Batch 200/469 | Gen/Dis Loss: 0.7653/0.7036\n",
      "Epoch: 065/100 | Batch 300/469 | Gen/Dis Loss: 0.7685/0.6466\n",
      "Epoch: 065/100 | Batch 400/469 | Gen/Dis Loss: 0.7480/0.6988\n",
      "Time elapsed: 12.06 min\n",
      "Epoch: 066/100 | Batch 000/469 | Gen/Dis Loss: 0.7193/0.6841\n",
      "Epoch: 066/100 | Batch 100/469 | Gen/Dis Loss: 0.7175/0.6873\n",
      "Epoch: 066/100 | Batch 200/469 | Gen/Dis Loss: 0.7521/0.6564\n",
      "Epoch: 066/100 | Batch 300/469 | Gen/Dis Loss: 0.6923/0.6908\n",
      "Epoch: 066/100 | Batch 400/469 | Gen/Dis Loss: 0.7063/0.7025\n",
      "Time elapsed: 12.25 min\n",
      "Epoch: 067/100 | Batch 000/469 | Gen/Dis Loss: 0.7407/0.7015\n",
      "Epoch: 067/100 | Batch 100/469 | Gen/Dis Loss: 0.7383/0.6728\n",
      "Epoch: 067/100 | Batch 200/469 | Gen/Dis Loss: 0.7197/0.7090\n",
      "Epoch: 067/100 | Batch 300/469 | Gen/Dis Loss: 0.7496/0.6714\n",
      "Epoch: 067/100 | Batch 400/469 | Gen/Dis Loss: 0.7678/0.6930\n",
      "Time elapsed: 12.43 min\n",
      "Epoch: 068/100 | Batch 000/469 | Gen/Dis Loss: 0.6839/0.7058\n",
      "Epoch: 068/100 | Batch 100/469 | Gen/Dis Loss: 0.7106/0.7098\n",
      "Epoch: 068/100 | Batch 200/469 | Gen/Dis Loss: 0.7275/0.6948\n",
      "Epoch: 068/100 | Batch 300/469 | Gen/Dis Loss: 0.7247/0.6653\n",
      "Epoch: 068/100 | Batch 400/469 | Gen/Dis Loss: 0.7031/0.7208\n",
      "Time elapsed: 12.62 min\n",
      "Epoch: 069/100 | Batch 000/469 | Gen/Dis Loss: 0.7105/0.6994\n",
      "Epoch: 069/100 | Batch 100/469 | Gen/Dis Loss: 0.7530/0.6780\n",
      "Epoch: 069/100 | Batch 200/469 | Gen/Dis Loss: 0.7811/0.6714\n",
      "Epoch: 069/100 | Batch 300/469 | Gen/Dis Loss: 0.7101/0.6895\n",
      "Epoch: 069/100 | Batch 400/469 | Gen/Dis Loss: 0.7741/0.6897\n",
      "Time elapsed: 12.82 min\n",
      "Epoch: 070/100 | Batch 000/469 | Gen/Dis Loss: 0.7459/0.6647\n",
      "Epoch: 070/100 | Batch 100/469 | Gen/Dis Loss: 0.7229/0.6980\n",
      "Epoch: 070/100 | Batch 200/469 | Gen/Dis Loss: 0.7142/0.6880\n",
      "Epoch: 070/100 | Batch 300/469 | Gen/Dis Loss: 0.7575/0.6888\n",
      "Epoch: 070/100 | Batch 400/469 | Gen/Dis Loss: 0.7443/0.6688\n",
      "Time elapsed: 12.99 min\n",
      "Epoch: 071/100 | Batch 000/469 | Gen/Dis Loss: 0.7392/0.6906\n",
      "Epoch: 071/100 | Batch 100/469 | Gen/Dis Loss: 0.7221/0.7070\n",
      "Epoch: 071/100 | Batch 200/469 | Gen/Dis Loss: 0.7066/0.7064\n",
      "Epoch: 071/100 | Batch 300/469 | Gen/Dis Loss: 0.7346/0.6812\n",
      "Epoch: 071/100 | Batch 400/469 | Gen/Dis Loss: 0.6982/0.7046\n",
      "Time elapsed: 13.18 min\n",
      "Epoch: 072/100 | Batch 000/469 | Gen/Dis Loss: 0.7182/0.7272\n",
      "Epoch: 072/100 | Batch 100/469 | Gen/Dis Loss: 0.7693/0.6998\n",
      "Epoch: 072/100 | Batch 200/469 | Gen/Dis Loss: 0.6934/0.7152\n",
      "Epoch: 072/100 | Batch 300/469 | Gen/Dis Loss: 0.7274/0.6977\n",
      "Epoch: 072/100 | Batch 400/469 | Gen/Dis Loss: 0.7920/0.6482\n",
      "Time elapsed: 13.37 min\n",
      "Epoch: 073/100 | Batch 000/469 | Gen/Dis Loss: 0.7348/0.7028\n",
      "Epoch: 073/100 | Batch 100/469 | Gen/Dis Loss: 0.7645/0.6819\n",
      "Epoch: 073/100 | Batch 200/469 | Gen/Dis Loss: 0.7096/0.7190\n",
      "Epoch: 073/100 | Batch 300/469 | Gen/Dis Loss: 0.7436/0.6871\n",
      "Epoch: 073/100 | Batch 400/469 | Gen/Dis Loss: 0.7205/0.6853\n",
      "Time elapsed: 13.57 min\n",
      "Epoch: 074/100 | Batch 000/469 | Gen/Dis Loss: 0.7573/0.6771\n",
      "Epoch: 074/100 | Batch 100/469 | Gen/Dis Loss: 0.7252/0.7207\n",
      "Epoch: 074/100 | Batch 200/469 | Gen/Dis Loss: 0.7440/0.6935\n",
      "Epoch: 074/100 | Batch 300/469 | Gen/Dis Loss: 0.6780/0.6983\n",
      "Epoch: 074/100 | Batch 400/469 | Gen/Dis Loss: 0.7433/0.7149\n",
      "Time elapsed: 13.75 min\n",
      "Epoch: 075/100 | Batch 000/469 | Gen/Dis Loss: 0.7384/0.6855\n",
      "Epoch: 075/100 | Batch 100/469 | Gen/Dis Loss: 0.7449/0.6909\n",
      "Epoch: 075/100 | Batch 200/469 | Gen/Dis Loss: 0.7297/0.6915\n",
      "Epoch: 075/100 | Batch 300/469 | Gen/Dis Loss: 0.7086/0.7055\n",
      "Epoch: 075/100 | Batch 400/469 | Gen/Dis Loss: 0.7717/0.6480\n",
      "Time elapsed: 13.92 min\n",
      "Epoch: 076/100 | Batch 000/469 | Gen/Dis Loss: 0.6886/0.7025\n",
      "Epoch: 076/100 | Batch 100/469 | Gen/Dis Loss: 0.7432/0.6995\n",
      "Epoch: 076/100 | Batch 200/469 | Gen/Dis Loss: 0.7580/0.6889\n",
      "Epoch: 076/100 | Batch 300/469 | Gen/Dis Loss: 0.7573/0.6869\n",
      "Epoch: 076/100 | Batch 400/469 | Gen/Dis Loss: 0.7179/0.6700\n",
      "Time elapsed: 14.11 min\n",
      "Epoch: 077/100 | Batch 000/469 | Gen/Dis Loss: 0.7178/0.6770\n",
      "Epoch: 077/100 | Batch 100/469 | Gen/Dis Loss: 0.7476/0.6653\n",
      "Epoch: 077/100 | Batch 200/469 | Gen/Dis Loss: 0.6809/0.7183\n",
      "Epoch: 077/100 | Batch 300/469 | Gen/Dis Loss: 0.7302/0.7057\n",
      "Epoch: 077/100 | Batch 400/469 | Gen/Dis Loss: 0.7666/0.6755\n",
      "Time elapsed: 14.30 min\n",
      "Epoch: 078/100 | Batch 000/469 | Gen/Dis Loss: 0.7105/0.7080\n",
      "Epoch: 078/100 | Batch 100/469 | Gen/Dis Loss: 0.7547/0.6769\n",
      "Epoch: 078/100 | Batch 200/469 | Gen/Dis Loss: 0.7441/0.6780\n",
      "Epoch: 078/100 | Batch 300/469 | Gen/Dis Loss: 0.7386/0.7000\n",
      "Epoch: 078/100 | Batch 400/469 | Gen/Dis Loss: 0.7264/0.7095\n",
      "Time elapsed: 14.48 min\n",
      "Epoch: 079/100 | Batch 000/469 | Gen/Dis Loss: 0.6915/0.7170\n",
      "Epoch: 079/100 | Batch 100/469 | Gen/Dis Loss: 0.7040/0.6950\n",
      "Epoch: 079/100 | Batch 200/469 | Gen/Dis Loss: 0.7102/0.7167\n",
      "Epoch: 079/100 | Batch 300/469 | Gen/Dis Loss: 0.7336/0.7043\n",
      "Epoch: 079/100 | Batch 400/469 | Gen/Dis Loss: 0.7293/0.7282\n",
      "Time elapsed: 14.65 min\n",
      "Epoch: 080/100 | Batch 000/469 | Gen/Dis Loss: 0.7565/0.6738\n",
      "Epoch: 080/100 | Batch 100/469 | Gen/Dis Loss: 0.7075/0.6976\n",
      "Epoch: 080/100 | Batch 200/469 | Gen/Dis Loss: 0.7109/0.6959\n",
      "Epoch: 080/100 | Batch 300/469 | Gen/Dis Loss: 0.7334/0.6856\n",
      "Epoch: 080/100 | Batch 400/469 | Gen/Dis Loss: 0.7357/0.6709\n",
      "Time elapsed: 14.84 min\n",
      "Epoch: 081/100 | Batch 000/469 | Gen/Dis Loss: 0.7483/0.6797\n",
      "Epoch: 081/100 | Batch 100/469 | Gen/Dis Loss: 0.7282/0.7087\n",
      "Epoch: 081/100 | Batch 200/469 | Gen/Dis Loss: 0.7219/0.6852\n",
      "Epoch: 081/100 | Batch 300/469 | Gen/Dis Loss: 0.7711/0.6864\n",
      "Epoch: 081/100 | Batch 400/469 | Gen/Dis Loss: 0.7182/0.6824\n",
      "Time elapsed: 15.03 min\n",
      "Epoch: 082/100 | Batch 000/469 | Gen/Dis Loss: 0.7293/0.6931\n",
      "Epoch: 082/100 | Batch 100/469 | Gen/Dis Loss: 0.7098/0.6946\n",
      "Epoch: 082/100 | Batch 200/469 | Gen/Dis Loss: 0.7255/0.6813\n",
      "Epoch: 082/100 | Batch 300/469 | Gen/Dis Loss: 0.7125/0.6940\n",
      "Epoch: 082/100 | Batch 400/469 | Gen/Dis Loss: 0.7094/0.6864\n",
      "Time elapsed: 15.21 min\n",
      "Epoch: 083/100 | Batch 000/469 | Gen/Dis Loss: 0.7273/0.6865\n",
      "Epoch: 083/100 | Batch 100/469 | Gen/Dis Loss: 0.7655/0.6898\n",
      "Epoch: 083/100 | Batch 200/469 | Gen/Dis Loss: 0.7437/0.6973\n",
      "Epoch: 083/100 | Batch 300/469 | Gen/Dis Loss: 0.7224/0.6992\n",
      "Epoch: 083/100 | Batch 400/469 | Gen/Dis Loss: 0.6938/0.6923\n",
      "Time elapsed: 15.40 min\n",
      "Epoch: 084/100 | Batch 000/469 | Gen/Dis Loss: 0.7416/0.6993\n",
      "Epoch: 084/100 | Batch 100/469 | Gen/Dis Loss: 0.7210/0.6955\n",
      "Epoch: 084/100 | Batch 200/469 | Gen/Dis Loss: 0.7025/0.7031\n",
      "Epoch: 084/100 | Batch 300/469 | Gen/Dis Loss: 0.7373/0.6893\n",
      "Epoch: 084/100 | Batch 400/469 | Gen/Dis Loss: 0.7306/0.7161\n",
      "Time elapsed: 15.57 min\n",
      "Epoch: 085/100 | Batch 000/469 | Gen/Dis Loss: 0.6902/0.6930\n",
      "Epoch: 085/100 | Batch 100/469 | Gen/Dis Loss: 0.6889/0.7020\n",
      "Epoch: 085/100 | Batch 200/469 | Gen/Dis Loss: 0.7513/0.6646\n",
      "Epoch: 085/100 | Batch 300/469 | Gen/Dis Loss: 0.7368/0.6782\n",
      "Epoch: 085/100 | Batch 400/469 | Gen/Dis Loss: 0.7356/0.6797\n",
      "Time elapsed: 15.76 min\n",
      "Epoch: 086/100 | Batch 000/469 | Gen/Dis Loss: 0.7178/0.6932\n",
      "Epoch: 086/100 | Batch 100/469 | Gen/Dis Loss: 0.7472/0.6727\n",
      "Epoch: 086/100 | Batch 200/469 | Gen/Dis Loss: 0.7381/0.6805\n",
      "Epoch: 086/100 | Batch 300/469 | Gen/Dis Loss: 0.7106/0.6993\n",
      "Epoch: 086/100 | Batch 400/469 | Gen/Dis Loss: 0.7434/0.6789\n",
      "Time elapsed: 15.94 min\n",
      "Epoch: 087/100 | Batch 000/469 | Gen/Dis Loss: 0.6928/0.7186\n",
      "Epoch: 087/100 | Batch 100/469 | Gen/Dis Loss: 0.7573/0.6784\n",
      "Epoch: 087/100 | Batch 200/469 | Gen/Dis Loss: 0.7347/0.6868\n",
      "Epoch: 087/100 | Batch 300/469 | Gen/Dis Loss: 0.6775/0.7108\n",
      "Epoch: 087/100 | Batch 400/469 | Gen/Dis Loss: 0.6929/0.6987\n",
      "Time elapsed: 16.12 min\n",
      "Epoch: 088/100 | Batch 000/469 | Gen/Dis Loss: 0.7251/0.6847\n",
      "Epoch: 088/100 | Batch 100/469 | Gen/Dis Loss: 0.6991/0.7062\n",
      "Epoch: 088/100 | Batch 200/469 | Gen/Dis Loss: 0.7497/0.6982\n",
      "Epoch: 088/100 | Batch 300/469 | Gen/Dis Loss: 0.7431/0.6628\n",
      "Epoch: 088/100 | Batch 400/469 | Gen/Dis Loss: 0.7292/0.6867\n",
      "Time elapsed: 16.30 min\n",
      "Epoch: 089/100 | Batch 000/469 | Gen/Dis Loss: 0.7114/0.6985\n",
      "Epoch: 089/100 | Batch 100/469 | Gen/Dis Loss: 0.7194/0.7012\n",
      "Epoch: 089/100 | Batch 200/469 | Gen/Dis Loss: 0.7152/0.7091\n",
      "Epoch: 089/100 | Batch 300/469 | Gen/Dis Loss: 0.7327/0.6929\n",
      "Epoch: 089/100 | Batch 400/469 | Gen/Dis Loss: 0.7291/0.7052\n",
      "Time elapsed: 16.50 min\n",
      "Epoch: 090/100 | Batch 000/469 | Gen/Dis Loss: 0.7195/0.6888\n",
      "Epoch: 090/100 | Batch 100/469 | Gen/Dis Loss: 0.7332/0.6896\n",
      "Epoch: 090/100 | Batch 200/469 | Gen/Dis Loss: 0.7231/0.7014\n",
      "Epoch: 090/100 | Batch 300/469 | Gen/Dis Loss: 0.7278/0.6994\n",
      "Epoch: 090/100 | Batch 400/469 | Gen/Dis Loss: 0.7176/0.7053\n",
      "Time elapsed: 16.69 min\n",
      "Epoch: 091/100 | Batch 000/469 | Gen/Dis Loss: 0.7328/0.7058\n",
      "Epoch: 091/100 | Batch 100/469 | Gen/Dis Loss: 0.7082/0.7012\n",
      "Epoch: 091/100 | Batch 200/469 | Gen/Dis Loss: 0.7348/0.6876\n",
      "Epoch: 091/100 | Batch 300/469 | Gen/Dis Loss: 0.7375/0.6844\n",
      "Epoch: 091/100 | Batch 400/469 | Gen/Dis Loss: 0.7533/0.7017\n",
      "Time elapsed: 16.87 min\n",
      "Epoch: 092/100 | Batch 000/469 | Gen/Dis Loss: 0.7177/0.7161\n",
      "Epoch: 092/100 | Batch 100/469 | Gen/Dis Loss: 0.7057/0.6844\n",
      "Epoch: 092/100 | Batch 200/469 | Gen/Dis Loss: 0.7255/0.6894\n",
      "Epoch: 092/100 | Batch 300/469 | Gen/Dis Loss: 0.7340/0.6790\n",
      "Epoch: 092/100 | Batch 400/469 | Gen/Dis Loss: 0.7173/0.6768\n",
      "Time elapsed: 17.04 min\n",
      "Epoch: 093/100 | Batch 000/469 | Gen/Dis Loss: 0.7081/0.6885\n",
      "Epoch: 093/100 | Batch 100/469 | Gen/Dis Loss: 0.7257/0.6966\n",
      "Epoch: 093/100 | Batch 200/469 | Gen/Dis Loss: 0.7400/0.6814\n",
      "Epoch: 093/100 | Batch 300/469 | Gen/Dis Loss: 0.7158/0.7051\n",
      "Epoch: 093/100 | Batch 400/469 | Gen/Dis Loss: 0.7222/0.6804\n",
      "Time elapsed: 17.24 min\n",
      "Epoch: 094/100 | Batch 000/469 | Gen/Dis Loss: 0.7450/0.6768\n",
      "Epoch: 094/100 | Batch 100/469 | Gen/Dis Loss: 0.7266/0.7039\n",
      "Epoch: 094/100 | Batch 200/469 | Gen/Dis Loss: 0.7201/0.6976\n",
      "Epoch: 094/100 | Batch 300/469 | Gen/Dis Loss: 0.7266/0.7124\n",
      "Epoch: 094/100 | Batch 400/469 | Gen/Dis Loss: 0.7196/0.6774\n",
      "Time elapsed: 17.44 min\n",
      "Epoch: 095/100 | Batch 000/469 | Gen/Dis Loss: 0.7398/0.6790\n",
      "Epoch: 095/100 | Batch 100/469 | Gen/Dis Loss: 0.7055/0.6950\n",
      "Epoch: 095/100 | Batch 200/469 | Gen/Dis Loss: 0.7315/0.6979\n",
      "Epoch: 095/100 | Batch 300/469 | Gen/Dis Loss: 0.7130/0.6876\n",
      "Epoch: 095/100 | Batch 400/469 | Gen/Dis Loss: 0.7167/0.6679\n",
      "Time elapsed: 17.61 min\n",
      "Epoch: 096/100 | Batch 000/469 | Gen/Dis Loss: 0.6865/0.6977\n",
      "Epoch: 096/100 | Batch 100/469 | Gen/Dis Loss: 0.7365/0.6776\n",
      "Epoch: 096/100 | Batch 200/469 | Gen/Dis Loss: 0.7084/0.7021\n",
      "Epoch: 096/100 | Batch 300/469 | Gen/Dis Loss: 0.7397/0.6880\n",
      "Epoch: 096/100 | Batch 400/469 | Gen/Dis Loss: 0.7080/0.7179\n",
      "Time elapsed: 17.78 min\n",
      "Epoch: 097/100 | Batch 000/469 | Gen/Dis Loss: 0.7208/0.6825\n",
      "Epoch: 097/100 | Batch 100/469 | Gen/Dis Loss: 0.7231/0.6816\n",
      "Epoch: 097/100 | Batch 200/469 | Gen/Dis Loss: 0.7159/0.6914\n",
      "Epoch: 097/100 | Batch 300/469 | Gen/Dis Loss: 0.7144/0.7064\n",
      "Epoch: 097/100 | Batch 400/469 | Gen/Dis Loss: 0.7088/0.7048\n",
      "Time elapsed: 17.98 min\n",
      "Epoch: 098/100 | Batch 000/469 | Gen/Dis Loss: 0.7247/0.7005\n",
      "Epoch: 098/100 | Batch 100/469 | Gen/Dis Loss: 0.7675/0.6761\n",
      "Epoch: 098/100 | Batch 200/469 | Gen/Dis Loss: 0.7218/0.6958\n",
      "Epoch: 098/100 | Batch 300/469 | Gen/Dis Loss: 0.7278/0.6866\n",
      "Epoch: 098/100 | Batch 400/469 | Gen/Dis Loss: 0.7532/0.6745\n",
      "Time elapsed: 18.15 min\n",
      "Epoch: 099/100 | Batch 000/469 | Gen/Dis Loss: 0.7019/0.6895\n",
      "Epoch: 099/100 | Batch 100/469 | Gen/Dis Loss: 0.7424/0.6801\n",
      "Epoch: 099/100 | Batch 200/469 | Gen/Dis Loss: 0.7447/0.6812\n",
      "Epoch: 099/100 | Batch 300/469 | Gen/Dis Loss: 0.7266/0.6907\n",
      "Epoch: 099/100 | Batch 400/469 | Gen/Dis Loss: 0.7336/0.6844\n",
      "Time elapsed: 18.33 min\n",
      "Epoch: 100/100 | Batch 000/469 | Gen/Dis Loss: 0.7321/0.6940\n",
      "Epoch: 100/100 | Batch 100/469 | Gen/Dis Loss: 0.6930/0.6972\n",
      "Epoch: 100/100 | Batch 200/469 | Gen/Dis Loss: 0.6985/0.6913\n",
      "Epoch: 100/100 | Batch 300/469 | Gen/Dis Loss: 0.7279/0.6904\n",
      "Epoch: 100/100 | Batch 400/469 | Gen/Dis Loss: 0.7286/0.7083\n",
      "Time elapsed: 18.47 min\n",
      "Total Training Time: 18.47 min\n"
     ]
    }
   ],
   "source": [
    "start_time = time.time()    \n",
    "\n",
    "discr_costs = []\n",
    "gener_costs = []\n",
    "for epoch in range(NUM_EPOCHS):\n",
    "    model = model.train()\n",
    "    for batch_idx, (features, targets) in enumerate(train_loader):\n",
    "\n",
    "        \n",
    "        # Normalize images to [-1, 1] range\n",
    "        features = (features - 0.5)*2.\n",
    "        features = features.view(-1, IMG_SIZE).to(device) \n",
    "\n",
    "        targets = targets.to(device)\n",
    "\n",
    "        valid = torch.ones(targets.size(0)).float().to(device)\n",
    "        fake = torch.zeros(targets.size(0)).float().to(device)\n",
    "        \n",
    "\n",
    "        ### FORWARD AND BACK PROP\n",
    "        \n",
    "        \n",
    "        # --------------------------\n",
    "        # Train Generator\n",
    "        # --------------------------\n",
    "        \n",
    "        # Make new images\n",
    "        z = torch.zeros((targets.size(0), LATENT_DIM)).uniform_(-1.0, 1.0).to(device)\n",
    "        generated_features = model.generator_forward(z)\n",
    "        \n",
    "        # Loss for fooling the discriminator\n",
    "        discr_pred = model.discriminator_forward(generated_features.view(targets.size(0), 1, 28, 28))\n",
    "        \n",
    "        gener_loss = F.binary_cross_entropy_with_logits(discr_pred, valid)\n",
    "        \n",
    "        optim_gener.zero_grad()\n",
    "        gener_loss.backward()\n",
    "        optim_gener.step()\n",
    "        \n",
    "        # --------------------------\n",
    "        # Train Discriminator\n",
    "        # --------------------------        \n",
    "        \n",
    "        discr_pred_real = model.discriminator_forward(features.view(targets.size(0), 1, 28, 28))\n",
    "        real_loss = F.binary_cross_entropy_with_logits(discr_pred_real, valid)\n",
    "        \n",
    "        discr_pred_fake = model.discriminator_forward(generated_features.view(targets.size(0), 1, 28, 28).detach())\n",
    "        fake_loss = F.binary_cross_entropy_with_logits(discr_pred_fake, fake)\n",
    "        \n",
    "        discr_loss = 0.5*(real_loss + fake_loss)\n",
    "\n",
    "        optim_discr.zero_grad()\n",
    "        discr_loss.backward()\n",
    "        optim_discr.step()        \n",
    "        \n",
    "        discr_costs.append(discr_loss.item())\n",
    "        gener_costs.append(gener_loss.item())\n",
    "        \n",
    "        \n",
    "        ### LOGGING\n",
    "        if not batch_idx % 100:\n",
    "            print ('Epoch: %03d/%03d | Batch %03d/%03d | Gen/Dis Loss: %.4f/%.4f' \n",
    "                   %(epoch+1, NUM_EPOCHS, batch_idx, \n",
    "                     len(train_loader), gener_loss, discr_loss))\n",
    "\n",
    "    print('Time elapsed: %.2f min' % ((time.time() - start_time)/60))\n",
    "    \n",
    "print('Total Training Time: %.2f min' % ((time.time() - start_time)/60))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nfor i in outputs:\\n    print(i.size())\\n'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### For Debugging\n",
    "\n",
    "\"\"\"\n",
    "for i in outputs:\n",
    "    print(i.size())\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEzCAYAAAA8bARZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOzdd3hUVfrA8e+bDqE3RUCKonQCBEVBQCwgNnRlVVBsCz9QYQFXZZcVse0idhRFVEBdxQKKSLHQewlSpEoLEEA6oYa08/vj3pnMJJM+k0ly38/z5MnMue3Mhdx37jnnvkeMMSillHKukGBXQCmlVHBpIFBKKYfTQKCUUg6ngUAppRxOA4FSSjlcWLArkF8hISGmTJkywa6GUkqVKOfOnTPGGJ9f/ktcIChTpgxnz54NdjWUUqpEEZHz2S3TpiGllHI4DQRKKeVwGgiUUsrhSlwfgVIq71JSUkhISCApKSnYVVFFJCoqitq1axMeHp7nbTQQKFWKJSQkUL58eerVq4eIBLs6KsCMMRw7doyEhATq16+f5+20aUipUiwpKYmqVatqEHAIEaFq1ar5vgPUQKBUKadBwFkK8u/tuEBwOimFH9btD3Y1lFKq2AhYIBCRCSJyWEQ25rBOZxFZJyKbRGRhoOriqfnIX/j7V+vYfOBUURxOKcc7dOgQvXr1okGDBrRp04ZrrrmG77//Pmj1WbBgAcuWLSv0Pm677TY/1Sj4AnlHMAnolt1CEakEvA/cYYxpCvQMYF0AWPTHEffrPcf06WSlAs0YQ48ePejYsSO7du1izZo1fPXVVyQkJAT0uKmpqdkuK0ggyGl/pUHAAoExZhFwPIdVegHfGWP22usfDlRdXLb9edr9+vi55EAfTinHmzdvHhEREfTv399dVrduXQYOHAhAWloaTz/9NG3btqVFixZ8+OGHgHWx7ty5M/fccw+NGjWid+/euGZTXLNmDZ06daJNmzZ07dqVgwcPAtC5c2f+9a9/0alTJ9555x1+/PFHrr76alq1asWNN97IoUOHiI+PZ9y4cbz11lvExMSwePFi9uzZww033ECLFi244YYb2Lt3LwAPP/wwQ4cO5frrr+fZZ5/N9jMeP36cHj160KJFC9q1a8eGDRsAWLhwITExMcTExNCqVStOnz7NwYMH6dixIzExMTRr1ozFixf7/6QXQDCHj14BhIvIAqA88I4x5jNfK4pIP6AfQERERIEPmJKe7n69cX9igfejVEn0wo+b/N4k2uSSCjx/e9Nsl2/atInWrVtnu/yTTz6hYsWKrF69mgsXLtC+fXtuvvlmANauXcumTZu45JJLaN++PUuXLuXqq69m4MCB/PDDD1SvXp2vv/6a4cOHM2HCBABOnjzJwoVWK/OJEydYsWIFIsLHH3/M6NGjeeONN+jfvz/lypXjH//4BwC33347ffr04aGHHmLChAkMGjSIadOmAfDHH38wZ84cQkNDs/0Mzz//PK1atWLatGnMmzePPn36sG7dOl5//XXGjh1L+/btOXPmDFFRUYwfP56uXbsyfPhw0tLSOHfuXP5OeIAEMxCEAW2AG4AywHIRWWGM+SPzisaY8cB4gOjo6AJPsjxn8yH368mr9vHfu1sUdFdKqQJ44oknWLJkCREREaxevZpffvmFDRs2MGXKFAASExPZvn07ERERXHXVVdSuXRuAmJgY4uPjqVSpEhs3buSmm24CrDuKmjVruvd/7733ul8nJCRw7733cvDgQZKTk7MdV798+XK+++47AB588EGeeeYZ97KePXvmGAQAlixZwtSpUwHo0qULx44dIzExkfbt2zN06FB69+7N3XffTe3atWnbti2PPvooKSkp9OjRg5iYmPyewoAIZiBIAI4aY84CZ0VkEdASyBII/OXQqQuB2rVSxV5O39wDpWnTpu6LJMDYsWM5evQosbGxgNWH8O6779K1a1ev7RYsWEBkZKT7fWhoKKmpqRhjaNq0KcuXL/d5vOjoaPfrgQMHMnToUO644w4WLFjAyJEj81Rnz+GXnvvLjqvJKvM+hg0bxq233sqsWbNo164dc+bMoWPHjixatIiZM2fy4IMP8vTTT9OnT5881SuQgjl89AfgOhEJE5GywNXAlkAeMCUtPfeVlFJ+06VLF5KSkvjggw/cZZ7NIV27duWDDz4gJSUFsJpickozf+WVV3LkyBF3IEhJSWHTpk0+101MTKRWrVoAfPrpp+7y8uXLc/p0Rn/htddey1dffQXAF198QYcOHfL1GTt27MgXX3wBWAGsWrVqVKhQgZ07d9K8eXOeffZZYmNj2bp1K3v27KFGjRr07duXxx57jN9++y1fxwqUgN0RiMhkoDNQTUQSgOeBcABjzDhjzBYR+QnY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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax1 = plt.subplot(1, 1, 1)\n",
    "ax1.plot(range(len(gener_costs)), gener_costs, label='Generator loss')\n",
    "ax1.plot(range(len(discr_costs)), discr_costs, label='Discriminator loss')\n",
    "ax1.set_xlabel('Iterations')\n",
    "ax1.set_ylabel('Loss')\n",
    "ax1.legend()\n",
    "\n",
    "###################\n",
    "# Set scond x-axis\n",
    "ax2 = ax1.twiny()\n",
    "newlabel = list(range(NUM_EPOCHS+1))\n",
    "iter_per_epoch = len(train_loader)\n",
    "newpos = [e*iter_per_epoch for e in newlabel]\n",
    "\n",
    "ax2.set_xticklabels(newlabel[::10])\n",
    "ax2.set_xticks(newpos[::10])\n",
    "\n",
    "ax2.xaxis.set_ticks_position('bottom')\n",
    "ax2.xaxis.set_label_position('bottom')\n",
    "ax2.spines['bottom'].set_position(('outward', 45))\n",
    "ax2.set_xlabel('Epochs')\n",
    "ax2.set_xlim(ax1.get_xlim())\n",
    "###################\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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xow21wEUI87Hk7vuustkL774osmiDlX1DUHO78n9999vzvE97gOlltRzs/yfJd966y1zTtShqvm/JERE5Cc/+YnJunfvbrL8X3bw6KOPmnOuvfbaSOvwOfvsswv+2LjxShEAAAAAAJBJbIoAAAAAAIBMYlMEAAAAAABkUpubIqo6VVXXquo7u2U9VPUlVV3c8l/7JiQAJUU3gTDRTSBMdBMIE91E0qIMWp0mIv8lIg/tlo0Vkb845yaq6tiW4/+McoP5g5iSGGDTsWNHk82cOdNkzc3NJosyWC5/0KKIyPXXX2+yq666ymSXXnqpyXwDrW677bac440bN5pz7rjjjj2uE6k3TWLsZrm1b2+//QwYMMBkvm5G4etvu3aFvzjON0TON7Q5f4Bsr169zDkNDQ0m6927d8FrQ3CmSYq7WWq+a339+vUm8z0/mDRpkslGjRplss6dOxe0tu9///sme/jhh03mex7hy959912T5Q/Q8z1nQMlME7rZqueee85kN998s8l27NhhMl9ffYMb58+fb7KampqoS0TlmiYBdtP3SwF8z1+L8fe//91kF198cc5x/i/YEBHp1KmTyUaMGGGyJ5980mSFDi5eu3atyXyD0levXh3p8x133HEFraMU2vwJwTn3NxHJf7Zyjoj8a4z7dBE5N+Z1AWgD3QTCRDeBMNFNIEx0E0kr9P827eOcWyUi0vLfVv8vTlUdrar1qlrv+39HAcSKbgJhoptAmOgmECa6ibIp+aBV59xk51ydc67O9zJyAMmgm0CY6CYQJroJhIluoliFvilqjar2c86tUtV+ImLfYNSKYt7THxff+x7jfn9YlNvs0qWLyZ555hmTXXLJJSZ74oknco5/97vfmXPGjRtnsv3222+P60TqFdzNShP395rly5ebbPjw4W1+nG8ewUknnRTLmpAqBXczhFlcUflmaJxwwgk5x5988ok5p7a21mR33XWXyc491756Os6u++Yn7Ny502RbtmwxWVNTk8luv/12kzFDJDiZfdz84x//mHOcP8dAxD8/xKdr164m830/mDVrlsl69OiRc+x7foxMSrybxfx86JtFN2fOHJP5erd06dKcY9/Pb+PHjzfZDTfcYLI4nzP45nX5nh/7ZpYMGjTIZKeddlo8C4tBoc8kZojI5S1/vlxE7GQmAEmgm0CY6CYQJroJhIluomyi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\n",
      "text/plain": [
       "<Figure size 1440x180 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "##########################\n",
    "### VISUALIZATION\n",
    "##########################\n",
    "\n",
    "\n",
    "model.eval()\n",
    "# Make new images\n",
    "z = torch.zeros((5, LATENT_DIM)).uniform_(-1.0, 1.0).to(device)\n",
    "generated_features = model.generator_forward(z)\n",
    "imgs = generated_features.view(-1, 28, 28)\n",
    "\n",
    "fig, axes = plt.subplots(nrows=1, ncols=5, figsize=(20, 2.5))\n",
    "\n",
    "\n",
    "for i, ax in enumerate(axes):\n",
    "    axes[i].imshow(imgs[i].to(torch.device('cpu')).detach(), cmap='binary')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------------------------------------------------------------\n",
      "        Layer (type)               Output Shape         Param #\n",
      "================================================================\n",
      "            Linear-1                 [-1, 3136]         313,600\n",
      "       BatchNorm1d-2                 [-1, 3136]           6,272\n",
      "         LeakyReLU-3                 [-1, 3136]               0\n",
      "          Reshape1-4             [-1, 64, 7, 7]               0\n",
      "   ConvTranspose2d-5           [-1, 32, 13, 13]          18,432\n",
      "       BatchNorm2d-6           [-1, 32, 13, 13]              64\n",
      "         LeakyReLU-7           [-1, 32, 13, 13]               0\n",
      "   ConvTranspose2d-8           [-1, 16, 25, 25]           4,608\n",
      "       BatchNorm2d-9           [-1, 16, 25, 25]              32\n",
      "        LeakyReLU-10           [-1, 16, 25, 25]               0\n",
      "  ConvTranspose2d-11            [-1, 8, 27, 27]           1,152\n",
      "      BatchNorm2d-12            [-1, 8, 27, 27]              16\n",
      "        LeakyReLU-13            [-1, 8, 27, 27]               0\n",
      "  ConvTranspose2d-14            [-1, 1, 28, 28]              32\n",
      "             Tanh-15            [-1, 1, 28, 28]               0\n",
      "================================================================\n",
      "Total params: 344,208\n",
      "Trainable params: 344,208\n",
      "Non-trainable params: 0\n",
      "----------------------------------------------------------------\n",
      "Input size (MB): 0.00\n",
      "Forward/backward pass size (MB): 0.59\n",
      "Params size (MB): 1.31\n",
      "Estimated Total Size (MB): 1.91\n",
      "----------------------------------------------------------------\n",
      "----------------------------------------------------------------\n",
      "        Layer (type)               Output Shape         Param #\n",
      "================================================================\n",
      "            Conv2d-1            [-1, 8, 14, 14]              72\n",
      "       BatchNorm2d-2            [-1, 8, 14, 14]              16\n",
      "         LeakyReLU-3            [-1, 8, 14, 14]               0\n",
      "            Conv2d-4             [-1, 32, 7, 7]           2,304\n",
      "       BatchNorm2d-5             [-1, 32, 7, 7]              64\n",
      "         LeakyReLU-6             [-1, 32, 7, 7]               0\n",
      "           Flatten-7                 [-1, 1568]               0\n",
      "            Linear-8                    [-1, 1]           1,569\n",
      "================================================================\n",
      "Total params: 4,025\n",
      "Trainable params: 4,025\n",
      "Non-trainable params: 0\n",
      "----------------------------------------------------------------\n",
      "Input size (MB): 0.00\n",
      "Forward/backward pass size (MB): 0.08\n",
      "Params size (MB): 0.02\n",
      "Estimated Total Size (MB): 0.10\n",
      "----------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "from torchsummary import summary\n",
    "model = model.to('cuda:0')\n",
    "summary(model.generator, input_size=(100,))\n",
    "summary(model.discriminator, input_size=(1, 28, 28))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
